package com.demo.mybaits.sqlsession;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.demo.mybaits.db.DataSourceProvider;
import com.demo.mybaits.model.dao.WebsitesMapper;

public enum SqlSessionProvider {

	INSTANCE;

	private final static Logger log = LoggerFactory.getLogger(SqlSessionProvider.class);
	
	// 每个请求创建一个sqlSession，每个sqlSession创建一个线程执行，保存sqlSession和线程信息
	// 发生异常时，关闭对应sqlSession
	private static Map<Thread, SqlSession> threadSqlSessionMap = new HashMap<>();

	SqlSessionFactory sqlSessionFactory = null;
	String resource = "mybaits-config.xml";
	InputStream is;

	public SqlSessionFactory init() {

		if (sqlSessionFactory != null) {
			return sqlSessionFactory;
		} else {
			try {
				InputStream is = Resources.getResourceAsStream(resource);
				sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
				log.info("SqlSessionFactory创建成功");
				return sqlSessionFactory;
			} catch (IOException e) {
				log.error("SqlSessionFactory创建失败！！");
				e.printStackTrace();
			}
		}
		return null;

	}

	public SqlSessionFactory init(DataSource dataSource) {

		if (sqlSessionFactory != null) {
			return sqlSessionFactory;
		} else {
			try {
				// 采用 MyBatis 的 JDBC 事务方式
				TransactionFactory transactionFactory = new JdbcTransactionFactory();
				Environment environment = new Environment("development", transactionFactory, dataSource);
				// 创建 Configuration 对象
				Configuration configuration = new Configuration(environment);
				// 加入一个映射器
				configuration.addMapper(WebsitesMapper.class);
				// 使用 SqlSessionFactoryBuilder 构建 SqlSessionFactory
				sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
				log.info("SqlSessionFactory创建成功，数据库："+dataSource.toString());
				return sqlSessionFactory;
			} catch (Exception e) {
				log.error("SqlSessionFactory创建失败，数据库："+dataSource.toString());
			}
		}

		return null;

	}

	public SqlSession getSessionByUri(String uri) {

		if (threadSqlSessionMap.get(Thread.currentThread()) != null) {
			return threadSqlSessionMap.get(Thread.currentThread());
		}
		SqlSession session = SqlSessionProvider.INSTANCE.init(DataSourceProvider.init("mysql")).openSession();
		threadSqlSessionMap.put(Thread.currentThread(), session);
		return session;
	}
	
	//获取当前线程的sqlSession
	public SqlSession getSession() {

		if (threadSqlSessionMap.get(Thread.currentThread()) != null) {
			return threadSqlSessionMap.get(Thread.currentThread());
		}
		SqlSession session = SqlSessionProvider.INSTANCE.init(DataSourceProvider.init("mysql")).openSession();
		threadSqlSessionMap.put(Thread.currentThread(), session);
		return session;
	}

	public void closeSqlSession() {
		try {
			SqlSession sqlSession = threadSqlSessionMap.remove(Thread.currentThread());
			sqlSession.close();
		} catch (Exception e) {
			log.error("关闭sqlsession发生异常", e);
		}
	}

	public static void main(String[] args) {
		SqlSessionProvider.INSTANCE.init(DataSourceProvider.init("mysql"));
	}
}
